package com.atguigu.gulimall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.cart.feign.ProductFeignService;
import com.atguigu.gulimall.cart.interceptor.CartInterceptor;
import com.atguigu.gulimall.cart.service.CartService;
import com.atguigu.gulimall.cart.vo.Cart;
import com.atguigu.gulimall.cart.vo.CartItem;
import com.atguigu.gulimall.cart.vo.SkuInfoVo;
import com.atguigu.gulimall.cart.vo.UserInfoTo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    ProductFeignService productService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ThreadPoolExecutor executor;

    private final String CART_PREFIX = "gulimall:cart:";


    @Override
    public CartItem addToCart(Long skuId, Integer num) {

        String cartKey = getUserCartKey();
//        购物车中是否有商品
        String s = (String) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if(s !=null){
            CartItem item = JSON.parseObject(s, CartItem.class);
            item.setCount(item.getCount() + num);
            redisTemplate.opsForHash().put(cartKey,skuId.toString(),JSON.toJSONString(item));
            return item;
        }

//        远程查询商品的信息
        CartItem cartItem = new CartItem();
        CompletableFuture<Void> skuInfoFuture = CompletableFuture.runAsync(() -> {

            R info = productService.info(skuId);
            SkuInfoVo skuInfo = info.getData("skuInfo", new TypeReference<SkuInfoVo>() {
            });
//        商品添加到购物车
            cartItem.setSkuId(skuId);
            cartItem.setCheck(true);
            cartItem.setImage(skuInfo.getSkuDefaultImg());
            cartItem.setTitle(skuInfo.getSkuTitle());
//        cartItem.setSkuAttr(skuInfo.get);
            cartItem.setCount(num);
            cartItem.setPrice(skuInfo.getPrice());
            cartItem.setTotalPrice(skuInfo.getPrice().multiply(new BigDecimal(num)));
        },executor);
        CompletableFuture<Void> attrFuture = CompletableFuture.runAsync(() -> {
            R result = productService.getSkuAttrValues(skuId);
            List<String> data = result.getData("data", new TypeReference<List<String>>() {
            });
            cartItem.setSkuAttr(data);
        }, executor);

        CompletableFuture.allOf(skuInfoFuture,attrFuture);

        redisTemplate.opsForHash().put(cartKey,skuId.toString(),JSON.toJSONString(cartItem));
        return cartItem;
    }

    @Override
    public CartItem getCartItem(Long skuId) {

        String s = (String) redisTemplate.opsForHash().get(getUserCartKey(), skuId.toString());
        if(s !=null) {
            return JSON.parseObject(s, CartItem.class);
        }
        return null;
    }

    @Override
    public Cart listCart(){
        String cartKey = getUserCartKey();
        return listCart(cartKey);
    }


    public Cart listCart(String cartKey) {

        List<Object> values = redisTemplate.opsForHash().values(cartKey);
        Cart cart = new Cart();
        if(values!=null && values.size() > 0){
            List<CartItem> collect = values.stream().map((object) -> {
                String s = object.toString();
                return JSON.parseObject(s,CartItem.class);
            }).collect(Collectors.toList());

            Integer count = collect.stream().map(CartItem::getCount).reduce(Integer::sum).get();
            cart.setItems(collect);
            cart.setCountNum(count);
            cart.setCountType(collect.size());
            BigDecimal amount = collect.stream().filter(CartItem::getCheck).map(CartItem::getTotalPrice).reduce(BigDecimal::add).get();
            cart.setAmount(amount);
        }
        return cart;
    }

    @Override
    public void checkItem(Long skuId, Integer check) {
        String json = (String)redisTemplate.opsForHash().get(getUserCartKey(), skuId);
        CartItem cartItem = JSON.parseObject(json, CartItem.class);
        cartItem.setCheck(check == 1);
        redisTemplate.opsForHash().put(getUserCartKey(),skuId,JSON.toJSONString(cartItem));
    }

    @Override
    public CartItem countChange(Long skuId, Integer num) {
        String json = (String)redisTemplate.opsForHash().get(getUserCartKey(), skuId);
        CartItem cartItem = JSON.parseObject(json, CartItem.class);
        cartItem.setCount(num);
        cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(num)));
        redisTemplate.opsForHash().put(getUserCartKey(),skuId,JSON.toJSONString(cartItem));
        return cartItem;
    }

    @Override
    public int deleteCartItem(Long skuId) {
        Long delete = redisTemplate.opsForHash().delete(getUserCartKey(), skuId.toString());
        return delete.intValue();
    }

    @Override
    public List<CartItem> getUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        if(userInfoTo.getUserId() == null){
            return null;
        }else{
            Cart cart = listCart();
            if(cart!=null){
                List<CartItem> items = cart.getItems();
                if(items!=null&&items.size() > 0){
                    List<CartItem> collect = items.stream().filter(CartItem::getCheck).peek(item ->{
//                        远程查询商品最新价格
//                        TODO  更新为最新价格
                        item.setPrice(productService.getPrice(item.getSkuId()));
                    }).collect(Collectors.toList());
//                    redis中存的购物车信息商品价格可能已经变动了，需要临时查询

                    return collect;
                }
            }
//            return listCart(cartKey);
        }
        return null;
    }


    private String getUserCartKey(){
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        String cartKey = "";
        if(userInfoTo.getUserId() !=null){
//            登陆了额用户
            cartKey = CART_PREFIX+userInfoTo.getUserId();
        }else{
            cartKey = CART_PREFIX+userInfoTo.getUserKey();
        }
        return cartKey;
    }
}
